package com.property.manage.service.system;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.property.manage.dao.system.RoleMapper;
import com.property.manage.model.system.Menu;
import com.property.manage.model.system.MenuVo;
import com.property.manage.model.system.Role;
import com.property.manage.model.system.RoleMenu;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 描述
 *
 * @author lwb
 * @since 2020/7/15
 */
@Component
@Slf4j
public class RoleService {

    private RoleMapper roleMapper;
    private RoleMenuService roleMenuService;
    private UserService userService;
    private MenuService menuService;

    public List<Role> getRoles(String roleName){
        QueryWrapper<Role> wrapper = new QueryWrapper<>();
        wrapper.like(StringUtils.isNotBlank(roleName), "role_name", roleName);

        return roleMapper.selectList(wrapper);
    }

    public List<MenuVo> getRoleMenu(Integer roleId){
        List<Menu> allMenus = menuService.getAllMenus();
        List<RoleMenu> roleMenus = roleMenuService.getRoleMenus(roleId);

        Set<Integer> roleMenuIds = roleMenus.stream().map(RoleMenu::getMenuId).collect(Collectors.toSet());

        for (Menu menu : allMenus) {
            if (Menu.TYPE_MENU.equals(menu.getType()) && roleMenuIds.contains(menu.getMenuId())) {
                menu.setChecked(true);
            } else {
                menu.setChecked(false);
            }
        }


        return menuService.convertToMenuVo(allMenus);
    }

    public void add(String roleName){
        Role role = new Role();
        role.setRoleName(roleName);

        roleMapper.insert(role);
    }

    @Transactional(rollbackFor = Exception.class)
    public void delete(Integer roleId){
        roleMapper.deleteById(roleId);
        roleMenuService.deleteRoleMenu(roleId);
        userService.deleteUserRole(roleId);
    }

    public void update(Integer roleId, String roleName){
        Role role = new Role();
        role.setRoleId(roleId);
        role.setRoleName(roleName);
        roleMapper.updateById(role);
    }

    @Transactional(rollbackFor = Exception.class)
    public void updateMenu(Integer roleId, String menuIdStr){
        List<Integer> menuIds = new Gson().fromJson(menuIdStr, new TypeToken<List<Integer>>() {
        }.getType());

        updateMenu(roleId, menuIds);
    }


    private void updateMenu(Integer roleId, List<Integer> menuIds){
        roleMenuService.deleteRoleMenu(roleId);

        List<Menu> allMenu = menuService.getAllMenus();
        Map<Integer, Menu> menuMap = allMenu.stream().collect(Collectors.toMap(Menu::getMenuId, Function.identity()));
        Set<Integer> allRoleMenuId = new HashSet<>();
        for (Integer menuId : menuIds) {
            Set<Integer> menuAndDir = new HashSet<>();
            menuService.selfAndAncestors(menuAndDir, menuMap, menuId);

            allRoleMenuId.addAll(menuAndDir);
        }

        roleMenuService.batchInsert(roleId, allRoleMenuId);
    }

    Role findRole(Integer roleId){
        return roleMapper.selectById(roleId);
    }



    @Autowired
    public void setRoleMapper(RoleMapper roleMapper) {
        this.roleMapper = roleMapper;
    }

    @Autowired
    public void setRoleMenuService(RoleMenuService roleMenuService) {
        this.roleMenuService = roleMenuService;
    }

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    @Autowired
    public void setMenuService(MenuService menuService) {
        this.menuService = menuService;
    }
}
